package com.cskaoyan.javase.object._5finalize;

import java.util.Scanner;

/**
 * 仅做了解,finalize方法
 * finalize方法在Java中,是一个比较失败的设计.它是模仿借鉴自C++中的析构函数,来实现析构函数的作用,但是没有成功.
 *
 * C++中和对象生命周期相关的两个函数:
 *      1.和对象的"出生"相关的,构造函数.对应Java的构造器或者构造方法
 *      2.和对象的"销毁"相关的,析构函数.对应Java的finalize方法
 *          析构函数的作用是在销毁对象的同时,释放对象所占内存空间的同时,释放掉对象所占用的系统资源
 *          对象往往会占用两种资源:
 *              1.自身存储所占的内存空间
 *              2.对象实现功能,需要占用系统的额外资源.
 *                 (比如对象做IO操作时,需要占用的系统IO资源,还有做数据库操作时
 *                 占用数据库资源,网络操作时,占用的网络资源)
 *         资源1,往往都可以正常释放资源,而资源2也需要释放,
 *         如果对象一直占用系统资源,就会导致系统资源一直被占用却不使用的情况.
 *         C++的析构函数就是来释放对象所占的额外资源的,做对象"销毁"的善后工作
 *         finalize方法和析构函数类似,也是在对象销毁的同时被JVM自动调用,
 *         理想情况下,Java程序员也可以把释放资源代码写入finalize方法
 *         达到销毁对象的同时,释放对象所占系统资源的目的.
 *         但是这种想法是实现不了的(C++中可以实现,Java中不行)
 *         这和GC是相关的,C++中的对象销毁具有准时性和确定性,析构函数的执行也具有确定性,能够及时的释放系统资源
 *         但是Java的GC具有不确定性和非准时性,连带着finalize方法的执行也是不确定的
 *         释放资源是非常重要的事情,重要的事情不能交给不靠谱的"人"做,释放资源需要及时释放
 *         所以Java中的,对象所占资源释放是全手动的,需要程序员手动完成,这样才能保证及时释放资源.
 *
 *  Object类当中的finalize方法
 *  finalize方法的声明和方法体比较简单，如下：
 * protected void finalize() throws Throwable { }
 * 首先注意访问权限是protected，这说明在不重写访问权限的情况下，仅能够在自身类中创建自身对象，才能调用这个方法。
 * 其次它的方法体是空的，功能没有实现，这种设计的目的是为了让子类自己去重写该方法的实现。这种做法比起抽象方法的强制子类实现，要更加灵活，而且可以用在普通类中。
 *
 * 最后，它的方法声明中有一个throws Throwable，这是方法抛出异常列表的声明，现在不用管它，后面会讲。
 *
 * 
 * @since 15:45
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 创建匿名对象
        new A();
        // 通知GC进行垃圾回收,一旦GC回收匿名对象A,那么该类的finalize方法会自动执行
        System.gc();

        Scanner sc = new Scanner(System.in);
        // 使用完毕Scanner对象后,标准流程是需要手动释放IO资源的
        sc.close();
        int num = sc.nextInt();
    }
}

class A{
    @Override
    protected void finalize() throws Throwable {
        System.out.println("模拟释放资源!");
    }
}
